/*
   @Copyright:LibreOJ
   @Author:   tjyemail
   @Problem:  https://loj.ac/problem/102
   @Language: C++
   @Datetime: 20-08-19 14:07
   */
// Edmonds Karp + Shortest Path Fast Algorithm (SPFA) , time 2834ms

#include <bits/stdc++.h>
using namespace std;

#define VERTEX 405
#define EDGE 15005
// adjacency list
struct Edge {
	int v, cap, price, rev; // cost = cap * price
	Edge(int v=0, int cap=0, int price=0, int rev=0):v(v), cap(cap), price(price), rev(rev){}
};
vector<Edge> edges[VERTEX];
inline void add(int a, int b, int c, int p) {
	edges[a].push_back(Edge(b, c, p, edges[b].size()));
	edges[b].push_back(Edge(a, 0, -p, edges[a].size()-1));
}
int costs[VERTEX], flows[VERTEX]; // s->k cost, flow
int paths[VERTEX]; // pre-node
int positions[VERTEX];

bool spfa(int v, int s, int t) {
	for(int i=0; i++<v; costs[i]=flows[i]=INT_MAX);
	costs[s] = 0;
	queue<int> vs;
	for(vs.push(s); !vs.empty(); vs.pop()) {
		s = vs.front();
		for(int k=0; k<edges[s].size(); ++k) {
			const Edge &ek = edges[s][k];
			if (ek.cap>0 && costs[ek.v] > costs[s]+ek.price) {
				costs[ek.v] = costs[s]+ek.price;
				flows[ek.v] = min(flows[s], ek.cap);
				paths[ek.v] = s; // record pre-node s
				positions[ek.v] = k;
				vs.push(ek.v);
			}
		}
	}
	return costs[t]!=INT_MAX; // check if it has path s -> t
}

void minicost(int v, int s, int t) {
	int flow = 0, cost = 0;
	while(spfa(v, s, t)) { // found shortest path
		// update available capacity flow
		for(int k=t; k!=s; k=paths[k]) {
			Edge &ek = edges[paths[k]][positions[k]];
			// now, k == ek.v
			ek.cap -= flows[t];
			edges[k][ek.rev].cap += flows[t];
		}
		flow += flows[t];
		cost += costs[t]*flows[t];
	}
	printf("%d %d\n", flow, cost);
}

int main()
{
	int v, e, a, b, c, p; // vertex, edge
	scanf("%d %d", &v, &e);
	for(int i=0; i++<e; ) {
		scanf("%d %d %d %d", &a, &b, &c, &p); // a->b, capacity, price
		add(a, b, c, p);
	}
	minicost(v, 1, v);
	return 0;
}
